/*
 *  image.c
 *  Ray Tracer
 *
 *  Created by Chirantan Ekbote on 10/5/10.
 *  Copyright 2010 Ohio State University. All rights reserved.
 *
 */

#include "../include/image.h"

image imageInit(int width, int height) {
	image temp = {0, width, height};
	
	// allocate memory for raster
	temp.raster = (rgb**) malloc(width * sizeof(rgb*));	
	int i;
	for (i = 0; i < width; i++) {
		temp.raster[i] = (rgb*) malloc(height * sizeof(rgb));
	}
	
	return temp;
}

image imageBackgroundInit(int width, int height, const rgb* background) {
	image temp = {0, width, height};
	
	// allocate memory for raster
	temp.raster = (rgb**) malloc(width * sizeof(rgb*));	
	int i, j;
	for (i = 0; i < width; i++) {
		temp.raster[i] = (rgb*) malloc(height * sizeof(rgb));
		
		// assign 'background' to each element
		for (j = 0; j < height; j++) {
			temp.raster[i][j] = (*background);
		}
	}
	
	return temp;
}

int imageSetPixel(image* pix, int x, int y, const rgb* color) {
	// check for out of bounds
	if (x < 0 || x > pix->x) { return 0; }
	if (y < 0 || y > pix->y) { return 0; }
	
	pix->raster[x][y] = (*color);
	return 1;
}

void imageGammaCorrect(image* pix, float gamma) {
	rgb temp;
	float power = 1.0f / gamma;
	int i, j;
	for (i = 0; i < pix->x; i++) {
		for (j = 0; j < pix->y; j++) {
			temp = pix->raster[i][j];
			pix->raster[i][j] = makeRGB(pow(temp.r, power), 
										pow(temp.g, power), 
										pow(temp.b, power));
		}
	}
}

// writes image as ppm
void imageWritePPM(const image* pix, const char* filename) {
	FILE *fp;
	
	if ((fp = fopen(filename, "w")) != NULL) {
		// output header
		fprintf(fp, "P6\n");
		fprintf(fp, "%d %d\n", pix->x, pix->y);
		fprintf(fp, "255\n");
		
		int i, j;
		unsigned int red, green, blue;
		
		// output clamped [0, 255] values
		for (j = pix->y-1; j >= 0; j--) {	// (0,0) of image is bottom left
			for (i = 0; i < pix->x; i++) {
				red = (unsigned int)(256 * pix->raster[i][j].r);
				green = (unsigned int)(256 * pix->raster[i][j].g);
				blue = (unsigned int)(256 * pix->raster[i][j].b);
				
				if (red > 255) { red = 255; }
				if (green > 255) { green = 255; }
				if (blue > 255) { blue = 255; }
				
				putc((unsigned char)(red), fp);
				putc((unsigned char)(green), fp);
				putc((unsigned char)(blue), fp);
			}
		}
		fclose(fp);
	} else {
		fprintf(stderr, "%s: error writing image to file\n", filename);
		exit(EXIT_FAILURE);
	}
}

// reads in a binary ppm
void imageReadPPM(image* pix, const char* filename) {
	// open input file
	FILE *fp;
	
	if ((fp = fopen(filename, "r")) != NULL) {
		char ch, type, red, green, blue;
		int i, j, cols, rows, num;
		
		// read in header info
		ch = getc(fp);
		type = getc(fp);
		fscanf(fp, "%d%d%d", &cols, &rows, &num);
		
		pix->x = cols;
		pix->y = rows;
		
		// allocate memory for raster
		pix->raster = (rgb**) malloc(cols * sizeof(rgb*));	
		for (i = 0; i < cols; i++) {
			pix->raster[i] = (rgb*) malloc(rows * sizeof(rgb));
		}
		
		// clean up newline
		ch = getc(fp);
		
		// store PPM pixel values in raster
		for (j = pix->y-1; j >= 0; j--) {	// (0,0) of image is bottom left
			for (i = 0; i < pix->x; i++) {
				red = getc(fp);
				green = getc(fp);
				blue = getc(fp);
				
				pix->raster[i][j] = makeRGB((float)((unsigned char) red) / 255.0f, 
											(float)((unsigned char) green) / 255.0f, 
											(float)((unsigned char) blue) / 255.0f);
			}
		}
		
	} else {
		fprintf(stderr, "%s: error opening ppm file\n", filename);
		exit(EXIT_FAILURE);
	}
	
}
